﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using TemplateFoundation.PageTypes;

namespace TemplateFoundation.Reflection
{
    /// <summary>
    /// Provides logic based on inheritance, such as finding related page types through reflection
    /// </summary>
    public class PageTypeInheritance
    {
        /// <summary>
        /// Retrieves a list of all page types that are related to the specified type by inheritance
        /// </summary>
        /// <param name="basePageType"></param>
        /// <returns></returns>
        public static IEnumerable<Type> FindPageTypeFamily(Type basePageType)
        {
            return FindPageTypeFamily(null, basePageType);
        }

        /// <summary>
        /// Returns the specified page type and all page types inheriting from it
        /// </summary>
        /// <param name="assembly"></param>
        /// <param name="basePageType"></param>
        /// <returns></returns>
        public static IEnumerable<Type> FindPageTypeFamily(Assembly assembly, Type basePageType)
        {
            if (assembly==null)
            {
                assembly = Inheritance.SiteAssembly;
            }

            if(assembly==null) // We cannot get the site assembly if there's no start page
            {
                return new List<Type>(0);       
            }

            var types = new List<Type> { basePageType };
                
            types.AddRange(Inheritance.FindDerivedTypes(assembly, basePageType).ToList());

            return types.Where(type => !type.IsAbstract);
        }

        /// <summary>
        /// Returns all relevant page types used for standard pages
        /// </summary>
        /// <returns></returns>
        /// <remarks>Page types such as those for date folders, tags etc are excluded</remarks>
        public static IEnumerable<Type> FindStandardPageTypes()
        {
            var types = FindPageTypeFamily(Inheritance.SiteAssembly, typeof(StandardPageBase));

            return types
                    .Where(type => 
                    !type.IsSubclassOf(typeof (ArticleListingPageBase)) && 
                    !type.IsSubclassOf(typeof (ArticlePageBase)))
                    .ToList();
        }

        /// <summary>
        /// Returns all relevant page types used for posts and articles
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Type> FindPostPageTypes()
        {
            return FindPageTypeFamily(Inheritance.SiteAssembly, typeof(ArticlePageBase));
        }
    }
}
